
import subprocess
import time
from datetime import datetime,timedelta
import requests
from apscheduler.jobstores.base import JobLookupError
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger
import os
import psutil
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure

MONGO_HOST = "localhost"  # 修改为你的MongoDB主机地址
MONGO_PORT = 27017        # 修改为你的MongoDB端口
MONGO_DB = "qnn" # 修改为你的数据库名
MONGO_COLLECTION = "wx_users" # 修改为你的集合名
RESTART_JOB_ID = "restart_wechat_daily"
scheduler = BlockingScheduler()
SCHEDULE_INTERVAL_HOURS = 6
# 全局MongoDB客户端
mongo_client = None
db = None

def init_mongodb():
    """初始化MongoDB连接"""
    global mongo_client, db
    try:
        mongo_client = MongoClient(
            host=MONGO_HOST,
            port=MONGO_PORT,
            serverSelectionTimeoutMS=5000  # 5秒超时
        )
        # 测试连接
        mongo_client.admin.command('ping')
        db = mongo_client[MONGO_DB]
        print("MongoDB连接成功")
        return True
    except ConnectionFailure as e:
        print(f"MongoDB连接失败: {e}")
        return False
    except Exception as e:
        print(f"MongoDB连接出现未知错误: {e}")
        return False

def close_program_by_name(process_name):
    """通过进程名称关闭程序"""
    for proc in psutil.process_iter(['name', 'pid']):
        try:
            # 检查进程名称是否匹配（不区分大小写）
            if process_name.lower() in proc.info['name'].lower():
                print(f"找到进程: {proc.info['name']} (PID: {proc.info['pid']})，准备关闭...")
                # 终止进程
                proc.terminate()
                # 等待进程终止
                try:
                    proc.wait(timeout=5)  # 最多等待5秒
                    print(f"进程 {proc.info['pid']} 已成功关闭")
                except psutil.TimeoutExpired:
                    # 如果优雅关闭失败，强制终止
                    print(f"进程 {proc.info['pid']} 关闭超时，尝试强制终止...")
                    proc.kill()
        except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
            pass

def start_program(program_path):
    """启动程序"""
    try:
        # 获取批处理文件所在的目录
        directory = os.path.dirname(program_path)
        subprocess.Popen(
            program_path,
            shell=True,
            cwd=directory  # 设置工作目录为批处理文件所在目录
        )
        # subprocess.Popen(program_path)
        print(f"程序 {program_path} 启动成功")
    except Exception as e:
        print(f"启动程序 {program_path} 失败: {e}")

def restart_wx_pad_prod():

    print("开始检查是否需要重启...")
    if not check_restart_condition():
        print("未满足重启条件，延迟1小时重启...")
        try:
            scheduler.reschedule_job(
                RESTART_JOB_ID,
                trigger='interval',
                hours=1  # 延迟1小时
            )
            print("检测到跳过条件，已重新安排任务到1小时后执行")
            return
        except JobLookupError:
            print("未找到定时任务")
            return
        except Exception as e:
            print(f"重新调度任务时出错: {e}")
            return

    print("开始关闭wechat_pad_prod程序...")
    close_program_by_name("wechatpadpro-windows")
    time.sleep(3)
    # 启动程序（需要替换为实际的程序路径）
    program_path = r"E:\wechat0723windos\run.bat"  # 请根据实际路径修改
    print("开始启动微信程序...")
    start_program(program_path)
    # time.sleep(10)
    # reset_connect()

    # 检查当前任务的调度间隔，如果不是标准间隔，则恢复
    try:
        job = scheduler.get_job(RESTART_JOB_ID)
        # 获取当前的触发器间隔
        current_hours = None
        if hasattr(job.trigger, 'interval'):
            # 计算间隔小时数
            interval = job.trigger.interval
            current_hours = interval.total_seconds() / 3600

        # 只有当当前间隔不是标准间隔时才重新设置
        if current_hours != SCHEDULE_INTERVAL_HOURS:
            scheduler.reschedule_job(
                RESTART_JOB_ID,
                trigger='interval',
                hours=SCHEDULE_INTERVAL_HOURS  # 恢复到标准的6小时间隔
            )
            print(f"重启完成，已恢复{SCHEDULE_INTERVAL_HOURS}小时重启间隔")
    except Exception as e:
        print(f"检查或恢复调度间隔时出错: {e}")


def check_restart_condition():
    """检查重启条件"""
    latest_message = db["chat_messages"].find_one({},sort=[("created_at", -1)])
    if not latest_message:
        print("未找到最近一条消息，请检查数据库")
        return True
    last_time = latest_message["created_at"]
    # 计算时间差
    current_time = datetime.now()
    time_diff = current_time - last_time
    if time_diff > timedelta(minutes=5):
        print("已超过5分钟，准备重启微信程序...")
        return True
    else:
        print(f"距离上次消息已不足5分钟，等待下次检查...")
        return False


def reset_connect():
    print("开始重连...")
    wx_users = db[MONGO_COLLECTION].find({"is_active": True})
    for wx_user in wx_users:
        params = {}
        api_url = f"http://192.168.1.85:1238/webhook/ResetConnection?key={wx_user['auth_key']}"
        try:
            print(f"正在重连: {api_url}")
            requests.post(api_url, json=params)
            print(f"重连成功: {api_url}")
        except Exception as e:
            print(f"重连失败: {api_url}")
            print(e)


def main():
    """
1    主函数，设置定时任务
    """
    if not init_mongodb():
        print("MongoDB初始化失败，程序退出")
        return



    # 添加定时任务 - 每天上午9点执行
    scheduler.add_job(
        func=restart_wx_pad_prod,
        trigger="interval",
        minutes=1,
        # hours=SCHEDULE_INTERVAL_HOURS,
        id=RESTART_JOB_ID,
        name='每日重启微信',
        replace_existing=True
    )
    print("定时任务已配置，每6小时执行一次，准备启动...")

    # 启动调度器（重要：这行代码是必须的）
    try:
        scheduler.start()
    except KeyboardInterrupt:
        print("定时任务已停止")
        scheduler.shutdown()

if __name__ == '__main__':
    main()